package org.rcy.ruicingmarket.interceptor;

import org.apache.commons.lang3.StringUtils;
import org.rcy.ruicingmarket.security.PrivilegeCheck;
import org.rcy.ruicingmarket.resource.ApiResource;
import org.rcy.ruicingmarket.resource.ResourceGroup;
import org.rcy.ruicingmarket.oss.user.OssUser;
import org.rcy.ruicingmarket.security.SecurityUserContext;
import org.rcy.ruicingmarket.resource.ApiResourceService;
import org.rcy.ruicingmarket.resource.ResourceGroupService;
import org.rcy.ruicingmarket.oss.role.RoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 吴康桥
 * @Description
 * @date 2022/10/27 11:47
 */


public class SecurityInterceptor implements HandlerInterceptor {
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private RoleService roleService;
	@Autowired
	private ApiResourceService apiResourceService;
	@Autowired
	private ResourceGroupService resourceGroupService;


	// 在preHandle中处理，并处理401情况。其他不处理
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
			if(request.getMethod().equals("OPTIONS")) {
				return true;
			}
			Collection<ResourceGroup> list = SecurityUserContext.getUserResourceGroups();
			String apiFullName = null;
			if(handler instanceof HandlerMethod){
				HandlerMethod handlerMethod = (HandlerMethod)handler;
				apiFullName = handlerMethod.getMethod().getDeclaringClass().getName() +"."+ handlerMethod.getMethod().getName();
				PrivilegeCheck privilegeCheck = handlerMethod.getMethodAnnotation(PrivilegeCheck.class);
				if(privilegeCheck == null){
					return false;
				}
				System.out.println(apiResourceService);
				ApiResource resource = apiResourceService.getByName(privilegeCheck.name());
				if(null == resource){//不需要进行权限验证
					//createLog(request, response, resource);
					resource = new ApiResource(privilegeCheck.group(), privilegeCheck.name(),apiFullName,privilegeCheck.auth());
					apiResourceService.createOrUpdate(resource);
				}
				if(!resource.isAuth()){
					return true;
				}

				//获取当前接口所属的资源组
				List<ResourceGroup> apiResourceGroup = resourceGroupService.getResourceGroupByApiName(privilegeCheck.name());
				if(!apiResourceGroup.isEmpty()){
					List<String> apiResourceGroupNames = apiResourceGroup.stream().map(r -> r.getName()).collect(Collectors.toList());
					List<String> uersResourceGroupNames = list.stream().map(r -> r.getName()).collect(Collectors.toList());
					//判断该用户与该接口资源组的交集
					if(apiResourceGroupNames.size() > uersResourceGroupNames.size()) {
						apiResourceGroupNames.retainAll(uersResourceGroupNames);
						if(apiResourceGroupNames.size() > 0){
							return true;
						}
					}
					else {
						uersResourceGroupNames.retainAll(apiResourceGroupNames);
						if(uersResourceGroupNames.size() > 0){
							return true;
						}
					}
				}
				}
			OssUser ossUser = SecurityUserContext.getOssUser();
			logger.warn("Access dinied,User:{},handler:{}", ossUser == null ? "null" : SecurityUserContext.getOssUser().getName(), handler);
			//没有权限，403 forbidden
			response.setStatus(HttpStatus.UNAUTHORIZED.value());
//		if (ossUser != null) {
//			createLog(request, response, null);
//		} else {
//			createLog(request, response, null, RequestIpAddressUtils.getIpAddress(request), "未知");
//		}
			response.getWriter().flush();
			return false;
	}


	private void createLog(HttpServletRequest request, HttpServletResponse response, PrivilegeCheck privilegeCheck) throws IOException {
		OssUser ossUser = SecurityUserContext.getOssUser();
		//createLog(request, response, authResource, account, name);
	}

//	private void createLog(HttpServletRequest request, HttpServletResponse response, PrivilegeCheck privilegeCheck,
//						   String account, String name) throws IOException {
//		OperateLog log = new OperateLog();
//
//		log.setAccount(account);
//		log.setUserName(name);
//		log.setOperateMenu(authResource == null ? "未知" : authResource.group().getName());
//		log.setOperateService(authResource == null ? "未知" : authResource.name());
//		log.setOperateTime(new Date());
//		log.setRequestBody(getRequestParam(request));
//		log.setUrl(request.getRequestURI());
//		log.setResponseCode(String.valueOf(response.getStatus()));
//
//		operateLogService.create(log);
//	}

//	private String getRequestParam(HttpServletRequest request) {
//		if (isNotRecordUrl(request.getRequestURI())) {
//			return null;
//		}
//		if (needReadRequestBody(request)) {
//			String result = HttpServletRequestUtil.requestBody(request);
//			result = StringUtils.deleteWhitespace(result);
//			return overLengthThenSubstring(result);
//		}
//		Enumeration<String> e = request.getParameterNames();
//		Map<String, String> map = new HashMap<>();
//		while (e.hasMoreElements()) {
//			String ele = e.nextElement();
//			String param = request.getParameter(ele);
//			if (StringUtils.isNotEmpty(param)) {
//				map.put(ele, param);
//			}
//		}
//		return overLengthThenSubstring(map.size() == 0 ? null : map.toString());
//	}

	private String overLengthThenSubstring(String body) {
		int maxRequestBodyLength = 4000;
		if (StringUtils.isBlank(body)) {
			return body;
		}
		if (StringUtils.length(body) > maxRequestBodyLength) {
			return body.substring(0,maxRequestBodyLength);
		}
		return body;
	}

//	private boolean isNotRecordUrl(String requestURI) {
//		// 过滤行业案例的请求体
//		return excludeUrlsProvider.contains(requestURI);
//	}
//
//
//	private boolean needReadRequestBody(HttpServletRequest request) {
//		return "application/json".equals(request.getContentType()) && request instanceof RepeatedlyReadRequestWrapper;
//	}
}
